package com.xdf.xzymanagementsystem.service.impl;

import com.xdf.xzymanagementsystem.dao.JcStoreMapper;
import com.xdf.xzymanagementsystem.entity.JcStore;
import com.xdf.xzymanagementsystem.enums.StorageEnum;
import com.xdf.xzymanagementsystem.service.CallProcedureService;
import com.xdf.xzymanagementsystem.util.Example;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xdf.xzymanagementsystem.entity.BillType;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import com.xdf.xzymanagementsystem.dao.BillTypeMapper;
import com.xdf.xzymanagementsystem.service.BillTypeService;

/**
 * @Description : com.xdf.xzymanagementsystem.service.impl(业务层实现类,该类为生成器自动生成).
 * @Author : 张柯
 * @Date : 2021-01-27 12:44:45
 */
@Service
public class BillTypeServiceImpl implements BillTypeService {
    @Autowired
    private BillTypeMapper dao;
    @Autowired
    private JcStoreMapper storeMapper;
    @Autowired
    private CallProcedureService callProcedureService;

    /**
     * @Describe 新增方法
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(BillType record) throws Exception {
        return dao.insert(record);
    }

    /**
     * @Describe 选择新增
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSelective(BillType record) throws Exception {
        return dao.insertSelective(record);
    }

    /**
     * @Describe 批量新增
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiInsert(List<BillType> list) throws Exception {
        return dao.multiInsert(list);
    }

    /**
     * @Describe 修改
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByPrimaryKey(BillType record) throws Exception {
        return dao.updateByPrimaryKey(record);
    }

    /**
     * @Describe 选择修改
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByPrimaryKeySelective(BillType record) throws Exception {
        return dao.updateByPrimaryKeySelective(record);
    }

    /**
     * @Describe 修改
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(BillType record) throws Exception {
        return dao.updateByPrimaryKey(record);
    }

    /**
     * @Describe 批量修改
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiUpdate(List<BillType> list) throws Exception {
        return dao.multiUpdate(list);
    }

    /**
     * @Describe 根据主键查询
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    public BillType selectByPrimaryKey(String id) throws Exception {
        return dao.selectByPrimaryKey(id);
    }

    /**
     * 获取成品单据类型
     * @param accessMode
     * @return
     * @throws Exception
     */
    @Override
    public BillType getBillType4ProductOrderBill(int accessMode) throws Exception {
        List<BillType> list1 = getBillType(StorageEnum.PRODUCT, accessMode);
        List<BillType> list2 = getBillType(StorageEnum.SEMI_FINISHED, accessMode);
        List<BillType> list = new ArrayList<>();
        if (list1 != null) {
            list.addAll(list1);
        }
        if (list2 != null) {
            list.addAll(list2);
        }
        return Optional.ofNullable(list).orElse(new ArrayList<>()).stream()
                .filter(item -> !Optional.ofNullable(item).map(BillType::getAllowManual).orElse(false))
                .filter(item -> item.getBillTypeName().contains(accessMode == 1 ? "成品入库" : "取消完工退回"))
                .findFirst().orElse(null);
    }

    /**
     * @Describe 根据主键删除
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByPrimaryKey(String id) throws Exception {
        return dao.deleteByPrimaryKey(id);
    }

    /**
     * @Describe 根据Entity查询
     * @author 张柯
     * @Date 2021-01-27 12:44:45
     */
    @Override
    public List<BillType> listQuery(BillType record) throws Exception {
        return dao.selectByParam(record);
    }

    @Override
    public List<BillType> listQuery(Example example) throws Exception {
        return dao.selectByExample(example);
    }

    /**
     * 计数
     *
     * @param example
     * @return
     */
    @Override
    public Long count(Example example) {
        return dao.countByExample(example);
    }

    /**
     * 获取指定仓库中的某一种类型单据
     *
     * @param storageType
     * @param accessMode
     * @return
     * @throws Exception
     */
    @Override
    public List<BillType> getBillType(StorageEnum storageType, int accessMode) throws Exception {
        if (storageType == null) return null;
        List<JcStore> storeList = getStorage(storageType);
        if (CollectionUtils.isEmpty(storeList)) return null;
        return dao.selectByExample(new Example()
                .andIn("storage_id", storeList.stream().map(JcStore::getId).toArray())
                .andEq("access_mode", accessMode));
    }

    /**
     * 获取单据类型
     *
     * @param storageType 仓库类别
     * @param accessMode  扣库方式
     * @return
     * @throws Exception
     */
    @Override
    public List<BillType> getBillType(String storageType, int accessMode, Boolean allowManual) throws Exception {
        if (StringUtils.isEmpty(storageType)) return null;
        List<StorageEnum> storageEnums = StorageEnum.matchArr(storageType);
        List<JcStore> storeList = new ArrayList<>();
        for (StorageEnum e : storageEnums) {
            List<JcStore> list = getStorage(e);
            if (CollectionUtils.isNotEmpty(list))
                storeList.addAll(list);
        }
        if (CollectionUtils.isEmpty(storeList)) return null;
        List<BillType> billTypeList = dao.selectByExample(new Example()
                .andIn("storage_id", storeList.stream().map(JcStore::getId).toArray())
                .andEq("access_mode", accessMode));
        if (allowManual == null) return billTypeList;
        return Optional.ofNullable(billTypeList).orElse(new ArrayList<>())
                .stream().filter(x -> allowManual == Optional.ofNullable(x).map(BillType::getAllowManual).orElse(false))
                .collect(Collectors.toList());
    }



    /**
     * 获取仓库
     *
     * @param storageType
     * @return
     */
    private List<JcStore> getStorage(StorageEnum storageType) {
        List<JcStore> storeList;
        switch (storageType) {
            case PRODUCT:
                storeList = storeMapper.selectByParam(JcStore.builder().isProduct(true).build());
                break;
            case MATERIAL:
                storeList = storeMapper.selectByParam(JcStore.builder().isMaterial(true).build());
                break;
            default:
                storeList = storeMapper.selectByParam(JcStore.builder().isSemiFinished(true).build());
        }
        return storeList;
    }

    @Override
    public List<BillType> getBillTypeManual(String storageId, Integer manual) throws Exception {
        Example<BillType> billTypeExample = new Example<>();
        if(storageId.length()<=0)
            billTypeExample.andIn("manual",manual);
        else
            billTypeExample.andIn("storage_id",storageId).andIn("manual",manual);
        return dao.selectByExample(billTypeExample);
    }

    /**
     * 返回材料入库单单据中“单据类型”下拉数据
     * @return
     * @throws Exception
     */
    @Override
    public List<BillType> getBillTypeMaterial() throws Exception {
//        return getBillTypeManual("jc",1);
        //return getBillTypeManual("",1);
        return callProcedureService.getMaterialBillType();
    }


}